/******************************************************************************
 *  _____     _____
 *  \  __\    \  __\
 *   \ \_\\    \ \_\\
 *    \  __\SS  \  __\roject
 *     \_\       \_\
 *
 * Mateusz Maciąg, Rafał Urbański
 * Komputerowe Systemy Sterowania
 *****************************************************************************/

#ifndef STEPWAVEFORM_H
#define STEPWAVEFORM_H


#include "WaveformBase.h"

// Przestrzeń nazw
namespace RafMat
{
namespace SimEngine
{

/**
    Klasa reprezentująca sygnał skoku jednostkowego.

    Skok może wystąpić w dowolnej chwili z dowolną wartością początkową
    i końcową. Klasa idedalnie nadaje się do testowania odpowiedzi
    skokowych układów dynamicznych. Wartość skoku podawana jest względem
    wartości początkowej i może być ujemna.

    Model matematyczny skoku jednostkowego:

    \f{eqnarray*}{ y(i) = y_0, \mbox{dla } i < T_p \\
                   y(i) = y_0 + A, \mbox{dla } i \geq T_p\f}
*/
class StepWaveform : public WaveformBase
{
public:

    /**
        Tworzy obiekt generatora skoku jednostkowego.

        Domyślnie tworzy skok jednostkowy przesunięty w czasie o 25 okresów próbkowania.

        \param [in] sim Obiekt symulacji rozporządzający tą instancją.
        \param [in] initVal Wartość początkowa (przed skokiem).
        \param [in] stepTime Chwila komutacji (skoku).
        \param [in] stepValue Wielkość skoku (wartość dodatnia lub ujemna).
    */
    explicit StepWaveform(SimInterface::ISimulator& sim,
                            double initVal = 0, double stepTime = 25,
                            double stepValue = 1);

    /**
        Zwraca aktualną wartość sygnału.
    */
    double getNextValue();

    /**
        Ustawia czas zajścia skoku.
        Wykorzystuje przedefiniowaną wartość okresu sygnału.
        \param [in] stepTime Moment skoku.
    */
    void setStepTime(double stepTime) { setPeriod(stepTime); }

    /**
        Ustawia wartość skoku.
        Wartość ustawiana jest względem wartości początkowej.
        Wykorzystuje przedefiniowaną wartość wzmocnienia sygnału.
        \param [in] stepVal Wartość skoku względem wartości początkowej.
    */
    void setStepVal(double stepVal) { setGain(stepVal); }

    /**
        Ustawia stan początkowy sygnału.
        Wykorzystuje przedefiniowaną wartość przesunięcia sygnału.
        \param [in] initVal Wartość początkowa.
    */
    void setInitVal(double initVal) { setOffset(initVal); }

    /**
        Zwraca moment zajścia skoku.
    */
    double getStepTime() const { return getPeriod(); }

    /**
        Zwraca wartość skoku.
    */
    double getStepVal() const { return getGain(); }

    /**
        Zwraca wartość początkową sygnału.
    */
    double getInitVal() const { return getOffset(); }

    /**
        Zmienia ustawienia parametru za pomocą łańcuchów znakowych.
        Wspierane parametry:
        - \c action_time
        - \c init_val
        - \c action_val

        \param [in] param Parametr, pod którym zapisujemy.
        \param [in] value Wartość, którą zapisujemy.
        \return True, w przypadku powodzenia.
    */
    virtual bool setParameter(const std::string& param, const std::string& value) throw(std::logic_error);

    /**
        Odczytuje parametr i zwraca jego wartość w formie łańcucha znaków.
        Wspierane parametry są takie same jak w setParameter.

        \param [in] param Parametr, który odczytujemy.
        \return Wartość odpowiadająca parametrowi.
    */
    virtual std::string getParameter(const std::string& param) const throw(std::logic_error);

    //SimFile::ConfigWriter& dumpParameters(SimFile::ConfigWriter& o) const;
    SimFile::ConfigWriter& dumpSpecificPar(SimFile::ConfigWriter& o) const;
private:

    // Stałe dla interfesjsu IConfigurable.
    static const std::string CONF_STEPTIME;
    static const std::string CONF_INIT;
    static const std::string CONF_STEPVALUE;
};

}   // SimEngine namespace
}   // RafMat namespace

#endif // STEPWAVEFORM_H
